package com.ylz.sjzx.sio.sdk.client.core;

import cn.hutool.core.util.StrUtil;
import com.corundumstudio.socketio.transport.NamespaceClient;
import com.ylz.sjzx.sio.common.core.constant.IMConstant;
import com.ylz.sjzx.sio.common.core.core.IAdapter;
import com.ylz.sjzx.sio.common.core.core.SioBase;
import com.ylz.sjzx.sio.common.core.core.container.common.annotation.AdapterDesc;
import com.ylz.sjzx.sio.common.core.enums.Cmd;
import com.ylz.sjzx.sio.common.core.enums.SocketModel;
import com.ylz.sjzx.sio.common.core.exception.PreParamException;
import com.ylz.sjzx.sio.sdk.client.session.IMSession;
import com.ylz.sjzx.sio.sdk.client.utils.SessionUtil;
import com.ylz.sjzx.sio.sdk.model.BaseSocketModel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * @author wiqi
 * @version 1.0
 * @date 2020/12/22
 */
@Slf4j
public class SocketProcess {

    /**
     * channel ws处理业务
     *
     * @param ctx
     * @param msg
     */
    public static void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        IMSession imSession = getSession(ctx.channel().id().asShortText());
        if (imSession == null) {
            log.error("登录异常 请重新登录channel.id{}", ctx.channel().id().asShortText());
            ctx.channel().close();
            return;
        }
        imSession.setSocketModel(SocketModel.channel);
        IMNioBase.setSession(imSession);
        String data = msg.text();
        log.debug("channelRead0初始入参data{}", data);
        //空响应
        if (StrUtil.isBlank(data)) {
            return;
        }
        int index = data.indexOf("[");
        if (index == -1) {
            log.debug("其他业务行为 基本是是心跳{}", data);
            //其他业务行为 基本是是心跳 有特殊情况再处理吧
            ctx.channel().writeAndFlush(new TextWebSocketFrame("3"));
        } else {
            String requestData = data.substring(index);
            //request data 转对象
            BaseSocketModel baseSocketModel = BaseSocketModel.toObj(requestData);

            if (IMNioBase.getTempauth() &&
                    imSession.isTemState() &&
                    !Objects.equals(baseSocketModel.getAction(), Cmd.manualLogin)) {
                //临时用户 但不是手动登录业务 不做处理
                log.warn("临时用户有限访问{}", imSession);
                return;
            }
            //正常业务
            SocketProcess.param(baseSocketModel).invoke();
        }
    }

    /**
     * socketIo事件处理
     *
     * @param namespaceClient
     * @param baseSocketModel
     */
    public static void socketIORead(NamespaceClient namespaceClient, BaseSocketModel baseSocketModel) {
        IMNioBase.clean();
        String sid = namespaceClient.get(IMConstant.IMSESSIONID);
        //从全局变量取数
        IMSession imSession = IMNioBase.getGlobalSession().get(sid);
        //IMSession imSession = getSession(sid);1

        if (imSession == null) {
            log.error("登录异常 请重新登录channel.id{}", sid);
            namespaceClient.getBaseClient().onChannelDisconnect();
            return;
        }
        imSession.setSocketModel(SocketModel.socketIo);
        IMNioBase.setSession(imSession);
        log.debug("channelRead0初始入参data{}", baseSocketModel);
        log.debug("登录用户信息{}", imSession);

        if (IMNioBase.getTempauth() &&
                imSession.isTemState() &&
                !Objects.equals(baseSocketModel.getAction(), Cmd.manualLogin)) {
            //临时用户 但不是手动登录业务 不做处理
            log.warn("临时用户有限访问{}", imSession);
            return;
        }
        //正常业务
        param(baseSocketModel).invoke();
    }

    public static IAdapter param(BaseSocketModel baseSocketModel) {

        IAdapter adapter = SioBase.getInnerAdapterMap().get(baseSocketModel.getAction().getValue());
        if (adapter == null) {
            log.error("adapter 为null 入参异常 连接关闭 data{}", baseSocketModel);
            throw new PreParamException("入参异常");
        }
        //将接口的desc注解存入context
        SioBase.setIAdapterDesc(adapter.getClass().getAnnotation(AdapterDesc.class));
        //正常请求参数数组两
        SioBase.setParam(baseSocketModel.getParam());
        return adapter;
    }

    private static IMSession getSession(String sid) {
        IMSession imSession = SessionUtil.getIMSessionService().getBySid(sid);
        if (imSession == null) {
            imSession = SessionUtil.getIMSessionService().getBySidTemp(sid);
        }
        return imSession;
    }
}
